//
//  MainState.cpp
//  trail-map-editor
//
//  Created by Tino Giorgio on 12/9/13.
//
//

#include "MainState.h"

#ifdef FREEGLUT_IS_PRESENT
#  include <GL/freeglut.h>
#else
#  ifdef __APPLE__
#    include <GLUT/glut.h>
#  else
#    include <GL/glut.h>
#  endif
#endif

#include <plib/js.h>
#include <plib/ssg.h>

#include "ui.h"

#include "Defines.h"

#include "TrailMapEditor.h"
#include "Map.h"
#include "Sector.h"

#define FOV_W 60.0
#define FOV_H 45.0
#define ORTHO_W 1024*4
#define ORTHO_H 768*4
#define NEAR 1
#define FAR 20000

// 225070 vinadio
// 225160 valdieri
// 226030 cuneo
// 226060 borgo san dalmazzo
// 227020 mondovi

#define DEBUG_INITIAL_SECTOR_ID "225160"

static sgVec4 smWhite             = { .9f, .9f, .9f, 1.0f } ;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

MainState::MainState()
: mSector(NULL)
{
    this->load("MainState.xml");
}

MainState::~MainState()
{
    scene->getRoot()->removeAllKids();
    
	// the mSector will be removed by the previous call
	
    delete scene;
}

void MainState::load(const char* filename)
{
	scene = new uiScene(filename);
	scene->setDelegate(this);
    
    scene->getRoot()->addKid(&mSectorTransform);
	
    uiSynthesize(scene, uiSlider, xSlider)
    uiSynthesize(scene, uiSlider, ySlider)
    uiSynthesize(scene, uiSlider, zoomSlider)
    uiSynthesize(scene, uiDial, headingDial)
    uiSynthesize(scene, uiDial, pitchDial)
    uiSynthesize(scene, uiDial, rollDial)
    uiSynthesize(scene, uiInput, headingInput)
    uiSynthesize(scene, uiInput, pitchInput)
    uiSynthesize(scene, uiInput, rollInput)
    uiSynthesize(scene, uiSlider, uSlider)
    uiSynthesize(scene, uiSlider, vSlider)
    uiSynthesize(scene, uiOneShot, loadDEMButton)
	uiSynthesize(scene, uiOneShot, loadSSGButton)
	uiSynthesize(scene, uiOneShot, saveSSGButton)
    uiSynthesize(scene, uiOneShot, exitButton)
    uiSynthesize(scene, uiButton, wireframeButton)
    uiSynthesize(scene, uiButton, projectionButton)
    uiSynthesize(scene, uiFileSelector, fileSelector)
	uiSynthesize(scene, uiSelectBox, mapSelectBox)
    uiSynthesize(scene, uiSelectBox, sectorSelectBox)
    
    headingInput->setValue(headingDial->getFloatValue());
    pitchInput->setValue(pitchDial->getFloatValue());
    rollInput->setValue(rollDial->getFloatValue());
    
    sgSetCoord(&mCameraCoord,
               xSlider->getFloatValue(),
               -zoomSlider->getFloatValue(),
               ySlider->getFloatValue(),
               0,
               0,
               0);
    
    ssgSetCamera ( & mCameraCoord ) ;
    ssgSetFOV     ( FOV_W, FOV_H ) ;
    ssgSetNearFar ( NEAR, FAR ) ;
    
    sgSetCoord(&mSectorCoord,
               0,
               0,
               0,
               headingDial->getFloatValue(),
               pitchDial->getFloatValue(),
               rollDial->getFloatValue());
    
    mSectorTransform.setTransform(&mSectorCoord);
    
    Sector::smWireframeEnabled = false;
    mOrthoCamera = false;
	
    uSlider->setValue(Sector::smMapOffsetU);
    uSlider->setLegend(uSlider->getStringValue());
    
    vSlider->setValue(Sector::smMapOffsetV);
    vSlider->setLegend(vSlider->getStringValue());
    
    char* mapPath = uiMakeResourcePath("Piemonte.xml");
    
	mMap = Map::loadFromXML(mapPath);
    
    DELETE_STRING(mapPath);
	
	sectorSelectBox->updateList(mMap->getSectors());
	
#ifdef DEBUG_INITIAL_SECTOR_ID
    _loadSector(DEBUG_INITIAL_SECTOR_ID);
#else
	_loadSector(sectorSelectBox->getStringValue());
#endif
	
	sgVec3 sunposn ;
	sgSetVec3 ( sunposn, 0, -10, 0 ) ;
	ssgGetLight( 0 ) -> setPosition( sunposn );
	
	ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, smWhite );
}

void MainState::display(void)
{    
    scene->display();
}

void MainState::resize(int w, int h)
{
    scene->resize(w, h);
}

void MainState::keyUp(unsigned char key, int x, int y)
{
	scene->keyUp(key, x, y);
}

void MainState::keyDown(unsigned char key, int x, int y)
{
	scene->keyDown(key, x, y);
}

void MainState::specialUp(int key, int x, int y)
{
	scene->specialUp(key, x, y);
}

void MainState::specialDown(int key, int x, int y)
{
	scene->specialDown(key, x, y);
}

void MainState::motion(int newx, int newy)
{
	scene->motion(newx, newy);
}

void MainState::passive(int newx, int newy)
{
	scene->passive(newx, newy);
}

void MainState::mouse(int button, int state, int x, int y)
{
	scene->mouse(button,state,x,y);
}

State* MainState::idle(void)
{
    return this;//(State *)new IntroState();
}

// uiSceneDelegate
void MainState::onCallback(const uiScene* scene, const uiView* view, const char* name, puObject* object)
{
	printf("onCallback(%p - %p,\"%s\",%s)\n",scene, view, name, object->getTypeString());
    
	if(ulStrEqual(name, "exitButton"))
	{
        uiApplication::getInstance().shutdown();
	}
    else if(object == headingDial)
	{
        SGfloat heading = headingDial->getFloatValue();
        
		headingInput->setValue(heading);
        
        mSectorCoord.hpr[0] = heading;
        
        mSectorTransform.setTransform(&mSectorCoord);
	}
    else if(object == pitchDial)
	{
        SGfloat pitch = pitchDial->getFloatValue();
        
		pitchInput->setValue(pitch);
        
        mSectorCoord.hpr[1] = pitch;
        
        mSectorTransform.setTransform(&mSectorCoord);
	}
    else if(object == rollDial)
	{
        SGfloat roll = rollDial->getFloatValue();
        
		rollInput->setValue(roll);
        
        mSectorCoord.hpr[2] = roll;
        
        mSectorTransform.setTransform(&mSectorCoord);
	}
    else if(object == ySlider)
    {
        SGfloat y = ySlider->getFloatValue();
        
        mCameraCoord.xyz[SG_Z] = -y;
        
        ssgSetCamera(&mCameraCoord);
    }
    else if(object == xSlider)
    {
        SGfloat x = xSlider->getFloatValue();
        
        mCameraCoord.xyz[SG_X] = -x;
        
        ssgSetCamera(&mCameraCoord);
    }
    else if(object == zoomSlider)
    {
        SGfloat zoom = zoomSlider->getFloatValue();
        
        mCameraCoord.xyz[SG_Y] = -zoom;
        
        ssgSetCamera(&mCameraCoord);
    }
    else if(object == uSlider)
    {
        SGfloat u = uSlider->getFloatValue();
        
        Sector::smMapOffsetU = u;
        
        uSlider->setLegend(uSlider->getStringValue());
        
        _loadSector(sectorSelectBox->getStringValue());
    }
    else if(object == vSlider)
    {
        SGfloat v = vSlider->getFloatValue();
        
        Sector::smMapOffsetV = v;
        
        vSlider->setLegend(vSlider->getStringValue());
        
        _loadSector(sectorSelectBox->getStringValue());
    }
    else if(object == wireframeButton)
    {
        Sector::smWireframeEnabled = !Sector::smWireframeEnabled; // toggle
    }
    else if(object == projectionButton)
    {
        mOrthoCamera =  !mOrthoCamera;
        
        if(mOrthoCamera)
            ssgSetOrtho ( ORTHO_W, ORTHO_H);
        else
            ssgSetFOV( FOV_W, FOV_H );
    }
    else if(object == loadDEMButton)
    {
		_loadSector("207080");
    }
	else if(object == saveSSGButton)
	{
		if(mSector)
		{
            char* demFile = uiMakeResourcePath("207080.DEM");
            char* mapFile = uiMakeResourcePath("207080.map");
            
			bool result = Sector::convertDEMToBinary(demFile,mapFile);
            
            DELETE_STRING(demFile);
            DELETE_STRING(mapFile);
		
			printf("saveToMAP : %s",result ? "TRUE" : "FALSE");
		}
	}
	else if(object == loadSSGButton)
	{
		if(mSector)
        {
            mSectorTransform.removeKid(mSector);
            mSector = NULL;
        }
        
        char* mapFile = uiMakeResourcePath("207080.map");
        
        mSector = Sector::loadFromBinary(mapFile);//fileSelector->getStringValue());
        
        DELETE_STRING(mapFile);
        
        mSector->print();
        
        mSectorTransform.addKid(mSector);
	}
	else if(object == sectorSelectBox)
	{
		printf("Selected sector : %s", sectorSelectBox->getStringValue());
		
		_loadSector(sectorSelectBox->getStringValue());
	}
}

void MainState::onActiveCallback(const uiScene* scene, const uiView* view, const char* name, puObject* object)
{
	printf("onActiveCallback(%p - %p,\"%s\",%s)\n",scene, view, name, object->getTypeString());
}

void MainState::onDownCallback(const uiScene* scene, const uiView* view, const char* name, puObject* object)
{
	printf("onDownCallback(%p - %p,\"%s\",%s)\n",scene, view, name, object->getTypeString());
    
    if(object == headingInput)
	{
		headingDial->setValue(headingInput->getFloatValue());
	}
}

void MainState::_loadSector(const char* name)
{
	if(mSector)
	{
		mSectorTransform.removeKid(mSector);
		mSector = NULL;
	}
	
	char path[512];
	
	//sprintf(path,"DEM/%s.dem","test.bin");
	sprintf(path,"DEM/%s.dem",name);
    
    char* filename = uiMakeResourcePath(path);
    
	mSector = Sector::loadFromDEM(filename);//fileSelector->getStringValue());
    
    DELETE_STRING(filename);
    
	mSectorTransform.addKid(mSector);
}

